#!/usr/bin/python
'''
/*
 * This computer program is the confidential information and proprietary trade
 * secret of VistaraIT LLC.  Possessions and use of this program must  conform
 * strictly to the license agreement between the user and VistaraIT LLC.,  and
 * receipt or possession does not convey any rights to divulge, reproduce,  or
 * allow others to use this program without specific written authorization  of
 * VistaraIT LLC.
 * 
 * Copyright (c) 2014 VistaraIT, Inc. All rights reserved.
 */
'''

from urlparse import urlparse
import applicationproperties as properties
import logger
from logger import executeCommand
import base64, threading
from django.template.loader import render_to_string

class DebugAppliance():
    
    def __init__(self,appmanager):
        self.appmanager = appmanager

    def prepareDebugInfo(self):
        try:
            debugInfo = self.getDebugInfo()
            debugStr = render_to_string('config/debugInfo', { 'debugInfo': debugInfo })
            encDebugStr = base64.b64encode(debugStr).strip()
            return encDebugStr
        except:
            return ""

    def getDebugInfo(self):
        statusInfo = {}

        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "------------------------------")
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "|Connectivity Troubleshooting|" )
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "------------------------------" )

        dateInfo = self.appmanager.getDateTimeInfo()
        statusInfo['DATE'] = str(dateInfo.currentTimeStr)
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Date: " + statusInfo['DATE'])

        result = self.statusNIC()
        if result[0] == 0:
            statusInfo['NIC'] = [True, 'Ok']
            logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Network Ethernet Card : Ok")
        else:
            statusInfo['NIC'] = [False, result[1]]
            logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "NIC Not Ok : " + result[1])

        netInfo = self.appmanager.getNetworkInfo()
        ipaddr = netInfo['ipaddr']
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Appliance IP Address: " + ipaddr)
        if ipaddr != 'UNKNOWN':
            statusInfo['SA_IP'] = [True, ipaddr]
        else:
            statusInfo['SA_IP'] = [False, ipaddr]

        netmask = netInfo['subnet']
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Appliance Netmask: " + netmask)
        if netmask != 'UNKNOWN':
            statusInfo['SA_NM'] = [True, netmask]
        else:
            statusInfo['SA_NM'] = [False, netmask]

        gateway = netInfo['gateway']
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Appliance Gateway: " + gateway)
        if gateway != 'UNKNOWN' and gateway != '':
            statusInfo['SA_GW'] = [True, gateway]
            cmd = "/bin/ping -c 3 " + gateway
            result = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'packets transmitted'"
            result1 = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'Host Unreachable'"
            result2 = executeCommand(cmd, [], True)
            if result1[0] == 0:
                if result2[0] == 0:
                    output = "[Unreachable] " + result1[1]
                else:
                    output = result1[1]
            else:
                output = result[1]
            if result[0] == 0:
                statusInfo['GW_PING_STATUS'] = [True, output]
            else:
                statusInfo['GW_PING_STATUS'] = [False, output]
        else:
            statusInfo['SA_GW'] = [False, gateway]
            statusInfo['GW_PING_STATUS'] = [False, "Gateway not found"]

        dns1 = netInfo['dns1']
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Appliance DNS Server #1: " + dns1)
        if dns1 != '':
            statusInfo['SA_DNS1'] = [True, dns1]
            cmd = "/bin/ping -c 3 " + dns1
            result = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'packets transmitted'"
            result1 = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'Host Unreachable'"
            result2 = executeCommand(cmd, [], True)
            if result1[0] == 0:
                if result2[0] == 0:
                    output = "[Unreachable] " + result1[1]
                else:
                    output = result1[1]
            else:
                output = result[1]
            if result[0] == 0:
                statusInfo['DNS1_PING_STATUS'] = [True, output]
            else:
                statusInfo['DNS1_PING_STATUS'] = [False, output]
        else:
            statusInfo['SA_DNS1'] = [False, dns1]
            statusInfo['DNS1_PING_STATUS'] = [False, "DNS Server #1 not found"]

        dns2 = netInfo['dns2']
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Appliance DNS Server #1: " + dns2)
        if dns2 != '':
            statusInfo['SA_DNS2'] = [True, dns2]
            cmd = "/bin/ping -c 3 " + dns2
            result = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'packets transmitted'"
            result1 = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'Host Unreachable'"
            result2 = executeCommand(cmd, [], True)
            if result1[0] == 0:
                if result2[0] == 0:
                    output = "[Unreachable] " + result1[1]
                else:
                    output = result1[1]
            else:
                output = result[1]
            if result[0] == 0:
                statusInfo['DNS2_PING_STATUS'] = [True, output]
            else:
                statusInfo['DNS2_PING_STATUS'] = [False, output]
        else:
            statusInfo['SA_DNS2'] = [False, dns2]
            statusInfo['DNS2_PING_STATUS'] = [False, "DNS Server #2 not found"]
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Ping Status to Gateway: " + statusInfo['GW_PING_STATUS'][1])
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Ping Status to DNS #1: " + statusInfo['DNS1_PING_STATUS'][1])
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Ping Status to DNS #2: " + statusInfo['DNS2_PING_STATUS'][1])

        alert_server = ""
        try:
            alert_server = str(urlparse(self.appmanager.getRegistrationInfo()['alert_url']).netloc.strip())
        except:
            pass
        
        cloud_server = self.appmanager.getRegistrationInfo()['cloud_server'].strip()
        tunnel_server = self.appmanager.cfgmanager.getTunnelInfoProperty(self.appmanager.cfgmanager.TUNNEL_SERVER).strip()
        public_server = properties.TEST_PUBLIC_SERVER_NAME
        
        cloud_server_dns_status = callMethodThread(self.appmanager, 'dnsCheck', [cloud_server])
        alert_server_dns_status = callMethodThread(self.appmanager, 'dnsCheck', [alert_server])
        tunnel_server_dns_status = callMethodThread(self.appmanager, 'dnsCheck', [tunnel_server])
        public_server_dns_status = callMethodThread(self.appmanager, 'dnsCheck', [public_server])

        cloud_server_dns_status.start()
        alert_server_dns_status.start()
        tunnel_server_dns_status.start()
        public_server_dns_status.start()

        cloud_server_dns_status.join()
        alert_server_dns_status.join()
        tunnel_server_dns_status.join()
        public_server_dns_status.join()
        statusInfo['SUPPORT_SITE_DNS_STATUS'] = [cloud_server_dns_status.status, cloud_server_dns_status.result]
        statusInfo['WS_SERVER_DNS_STATUS'] = [alert_server_dns_status.status, alert_server_dns_status.result]
        statusInfo['CSN_SERVER_DNS_STATUS'] = [tunnel_server_dns_status.status, tunnel_server_dns_status.result]
        statusInfo['TEST_SERVER_DNS_STATUS'] = [public_server_dns_status.status, public_server_dns_status.result]

        if public_server:
            cmd = "/bin/ping -c 3 " + properties.TEST_PUBLIC_SERVER_NAME
            result = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'packets transmitted'"
            result1 = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'Host Unreachable'"
            result2 = executeCommand(cmd, [], True)
            if result1[0] == 0:
                if result2[0] == 0:
                    output = "[Unreachable] " + result1[1]
                else:
                    output = result1[1]
            else:
                output = result[1]
            if result[0] == 0:
                statusInfo['GOOGLE_PING_STATUS'] = [True, output]
            else:
                statusInfo['GOOGLE_PING_STATUS'] = [False, output]
        else:
            statusInfo['GOOGLE_PING_STATUS'] = [False, "NA"]
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Ping Status to Google: " + statusInfo['GOOGLE_PING_STATUS'][1])

        if cloud_server:
            cmd = "/bin/ping -c 3 " + cloud_server
            result = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'packets transmitted'"
            result1 = executeCommand(cmd, [], True)
            cmd = "echo \"" + result[1] + "\" | grep 'Host Unreachable'"
            result2 = executeCommand(cmd, [], True)
            if result1[0] == 0:
                if result2[0] == 0:
                    output = "[Unreachable] " + result1[1]
                else:
                    output = result1[1]
            else:
                output = result[1]
            if result[0] == 0:
                statusInfo['SUPPORT_PING_STATUS'] = [True, output]
            else:
                statusInfo['SUPPORT_PING_STATUS'] = [False, output]
        else:
            statusInfo['SUPPORT_PING_STATUS'] = [False, "NA"]
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Ping Status to Support Site: " + statusInfo['SUPPORT_PING_STATUS'][1])

        network_conn_type = self.appmanager.getProxySettings()['connection']
        cloud_server_conn_status = callMethodThread(self.appmanager, 'checkServerConnectivity', [cloud_server, 443])
        alert_server_conn_status = callMethodThread(self.appmanager, 'checkServerConnectivity', [alert_server, 443])
        tunnel_server_conn_status = callMethodThread(self.appmanager, 'checkServerConnectivity', [tunnel_server, self.appmanager.cfgmanager.getTunnelInfoProperty(self.appmanager.cfgmanager.TUNNEL_PORT)])

        cloud_server_conn_status.start()
        alert_server_conn_status.start()
        tunnel_server_conn_status.start()       
        
        cloud_server_conn_status.join()
        alert_server_conn_status.join()
        tunnel_server_conn_status.join()
        
        statusInfo['SUPPORT_CONN_STATUS'] = [cloud_server_conn_status.status, cloud_server_conn_status.result]
        statusInfo['AB_CONN_STATUS'] = [alert_server_conn_status.status, alert_server_conn_status.result]
        statusInfo['CSN_CONN_STATUS'] = [tunnel_server_conn_status.status, tunnel_server_conn_status.result]
    
        
        if network_conn_type != 'direct':
            public_server_conn_status = callMethodThread(self.appmanager, 'checkServerConnectivity', [public_server, properties.TEST_PUBLIC_SERVER_PORT])
            public_server_conn_status.start()
            public_server_conn_status.join()
            statusInfo['PROXY_CONN_STATUS'] = [public_server_conn_status.status, public_server_conn_status.result]


        if self.appmanager.isRegistered():
            statusInfo['REGISTRATION_STATUS'] = [True, "Ok"]
        else:
            statusInfo['REGISTRATION_STATUS'] = [False, "Appliance not yet registered."]

        if self.appmanager.isTunnelRunning():
            statusInfo['TUNNEL_STATUS'] = [True, "Ok"]
        else:
            statusInfo['TUNNEL_STATUS'] = [False, "Tunnel is not established."]
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Registration Status: " + statusInfo['REGISTRATION_STATUS'][1])
        logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Tunnel Status: " + statusInfo['TUNNEL_STATUS'][1])
        
        return statusInfo
    
    def statusNIC(self):
        cmd = "/usr/bin/sudo /sbin/ethtool eth0 | /bin/grep -i 'Link detected: yes'"
        return executeCommand(cmd, [], True)

class callMethodThread(threading.Thread):
    def __init__(self, appmanager, func, args=[]):
        threading.Thread.__init__(self)
        self.appmanager = appmanager
        self.result = None
        self.status = False
        self.methodName = func
        self.arguments = args

    def run(self):
        if self.methodName == "dnsCheck":
            self.status, self.result = self.appmanager.dnsCheck(self.arguments[0])
            logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "DNS Check of host " + self.arguments[0] + " : " + self.result)
        elif self.methodName == "checkServerConnectivity":
            self.status, _resp, self.result = self.appmanager.checkServerConnectivity(self.arguments[0], self.arguments[1])
            logger.logDebugMsgs(logger.DEBUG, 'debugInfo', "Connectivity Status of " + self.arguments[0] + " on port " + str(self.arguments[1]) + ": " + self.result)
